package com.evan.review.basic.array;

import android.os.Bundle;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import com.evan.review.R;
import java.util.Arrays;

/**
 * 数组基础示例
 * 
 * 本Activity演示Java数组的基本概念和使用方法，包括：
 * 1. 数组的声明和初始化
 * 2. 数组的访问和遍历
 * 3. 数组的常见操作
 * 4. 数组的边界处理
 * 5. 常见错误和注意事项
 * 
 * 面试要点：
 * - 数组的定义方式（多种语法）
 * - 数组边界的处理（防止越界）
 * - 数组与集合的区别与转换
 * - 多维数组的使用
 * - 数组拷贝方式与深浅拷贝区别
 */
public class ArrayBasicActivity extends AppCompatActivity {
    
    private TextView tvOutput;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_array_basic);
        
        tvOutput = findViewById(R.id.tv_output);
        
        // 演示数组基础操作
        demonstrateArrayBasics();
        
        // 演示数组遍历
        demonstrateArrayTraversal();
        
        // 演示数组操作
        demonstrateArrayOperations();
        
        // 演示数组边界问题
        demonstrateArrayBoundaries();
        
        // 演示多维数组
        demonstrateMultidimensionalArrays();
        
        // 演示常见错误
        demonstrateCommonErrors();
        
        // 演示面试常见问题
        demonstrateInterviewQuestions();
    }
    
    /**
     * 演示数组的基本声明和初始化
     */
    private void demonstrateArrayBasics() {
        StringBuilder output = new StringBuilder();
        output.append("=== 数组基本声明和初始化 ===\n\n");
        
        // 1. 正确的数组声明和初始化方式
        output.append("1. 正确的数组声明和初始化：\n");
        
        // 方式1：声明时指定大小
        int[] arr1 = new int[5];
        output.append("int[] arr1 = new int[5]; // 创建长度为5的整型数组\n");
        
        // 方式2：声明时初始化
        int[] arr2 = new int[]{1, 2, 3, 4, 5};
        output.append("int[] arr2 = new int[]{1, 2, 3, 4, 5}; // 创建并初始化数组\n");
        
        // 方式3：简写形式
        int[] arr3 = {1, 2, 3, 4, 5};
        output.append("int[] arr3 = {1, 2, 3, 4, 5}; // 简写形式\n");
        
        // 方式4：先声明后初始化
        output.append("\n// 先声明后初始化：\n");
        output.append("int[] arr4; // 只声明引用\n");
        output.append("arr4 = new int[5]; // 分配内存\n");
        output.append("arr4 = new int[]{1, 2, 3, 4, 5}; // 重新分配并初始化\n");
        
        // 方式5：C风格声明（不推荐，但需要了解）
        int arr5[] = new int[5];
        output.append("\n// C风格声明（不推荐）：\n");
        output.append("int arr5[] = new int[5]; // 方括号放在变量名后\n");
        
        // 2. 错误的数组声明和初始化方式
        output.append("\n2. 错误的数组声明和初始化：\n");
        output.append("int[] arr = [1, 2, 3]; // 错误：应该使用花括号{}\n");
        output.append("int[] arr = new int[]; // 错误：必须指定大小或提供初始值\n");
        output.append("int[] arr = {1, 2, 3}; arr[3] = 4; // 错误：数组越界\n");
        
        // 3. 数组的基本属性
        output.append("\n3. 数组的基本属性：\n");
        output.append("arr1.length = " + arr1.length + " // 数组长度（注意不是方法，没有括号）\n"); 
        output.append("arr1[0] = " + arr1[0] + " // 访问元素（默认值为0）\n");
        
        updateOutput(output.toString());
    }
    
    /**
     * 演示数组的遍历方式
     */
    private void demonstrateArrayTraversal() {
        StringBuilder output = new StringBuilder();
        output.append("\n=== 数组遍历方式 ===\n\n");
        
        int[] arr = {1, 2, 3, 4, 5};
        
        // 1. for循环遍历
        output.append("1. for循环遍历：\n");
        for (int i = 0; i < arr.length; i++) {
            output.append("arr[" + i + "] = " + arr[i] + "\n");
        }
        
        // 2. for-each循环遍历
        output.append("\n2. for-each循环遍历：\n");
        for (int num : arr) {
            output.append("num = " + num + "\n");
        }
        
        // 3. 使用Arrays工具类
        output.append("\n3. 使用Arrays工具类：\n");
        output.append("Arrays.toString(arr) = " + Arrays.toString(arr) + "\n");
        
        // 4. Java 8 Stream API（不常用但要了解）
        output.append("\n4. Java 8 Stream API：\n");
        output.append("Arrays.stream(arr).forEach(num -> System.out.println(num));\n");
        
        updateOutput(output.toString());
    }
    
    /**
     * 演示数组的常见操作
     */
    private void demonstrateArrayOperations() {
        StringBuilder output = new StringBuilder();
        output.append("\n=== 数组常见操作 ===\n\n");
        
        int[] arr = {5, 2, 8, 1, 9};
        
        // 1. 数组排序
        output.append("1. 数组排序：\n");
        Arrays.sort(arr);
        output.append("排序后：" + Arrays.toString(arr) + "\n");
        
        // 2. 数组复制
        output.append("\n2. 数组复制：\n");
        int[] copy1 = Arrays.copyOf(arr, arr.length);
        output.append("完整复制：" + Arrays.toString(copy1) + "\n");
        
        int[] copy2 = Arrays.copyOfRange(arr, 1, 3);
        output.append("部分复制：" + Arrays.toString(copy2) + "\n");
        
        int[] srcArray = {1, 2, 3, 4, 5};
        int[] destArray = new int[5];
        System.arraycopy(srcArray, 0, destArray, 0, srcArray.length);
        output.append("System.arraycopy：" + Arrays.toString(destArray) + "\n");
        
        // 3. 数组填充
        output.append("\n3. 数组填充：\n");
        int[] fillArr = new int[5];
        Arrays.fill(fillArr, 10);
        output.append("填充后：" + Arrays.toString(fillArr) + "\n");
        
        // 4. 数组查找
        output.append("\n4. 数组查找：\n");
        int index = Arrays.binarySearch(arr, 8);
        output.append("二分查找（仅适用于已排序数组）：\n");
        output.append("8的索引 = " + index + "\n");
        
        updateOutput(output.toString());
    }
    
    /**
     * 演示数组边界处理
     */
    private void demonstrateArrayBoundaries() {
        StringBuilder output = new StringBuilder();
        output.append("\n=== 数组边界处理 ===\n\n");
        
        int[] arr = {1, 2, 3, 4, 5};
        
        // 1. 安全的边界检查
        output.append("1. 安全的边界检查：\n");
        output.append("// 访问元素前先检查索引范围\n");
        output.append("int index = 3;\n");
        output.append("if (index >= 0 && index < arr.length) {\n");
        output.append("    int value = arr[index]; // 安全访问\n");
        output.append("}\n");
        
        // 2. 特殊索引处理
        output.append("\n2. 特殊索引处理：\n");
        output.append("// 访问第一个元素\n");
        output.append("if (arr.length > 0) {\n");
        output.append("    int first = arr[0];\n");
        output.append("}\n\n");
        
        output.append("// 访问最后一个元素\n");
        output.append("if (arr.length > 0) {\n");
        output.append("    int last = arr[arr.length - 1];\n");
        output.append("}\n");
        
        // 3. 循环中的边界处理
        output.append("\n3. 循环中的边界处理：\n");
        output.append("// 正确处理j-1的情况\n");
        output.append("for (int j = 0; j < arr.length; j++) {\n");
        output.append("    if (j > 0) { // 重要：检查索引边界\n");
        output.append("        int prev = arr[j-1]; // 安全地访问前一个元素\n");
        output.append("    }\n");
        output.append("}\n");
        
        output.append("\n// 正确处理j+1的情况\n");
        output.append("for (int j = 0; j < arr.length; j++) {\n");
        output.append("    if (j < arr.length - 1) { // 重要：检查索引边界\n");
        output.append("        int next = arr[j+1]; // 安全地访问后一个元素\n");
        output.append("    }\n");
        output.append("}\n");
        
        updateOutput(output.toString());
    }
    
    /**
     * 演示多维数组
     */
    private void demonstrateMultidimensionalArrays() {
        StringBuilder output = new StringBuilder();
        output.append("\n=== 多维数组 ===\n\n");
        
        // 1. 二维数组定义
        output.append("1. 二维数组定义：\n");
        int[][] matrix1 = new int[3][4]; // 3行4列
        output.append("int[][] matrix1 = new int[3][4]; // 3行4列\n");
        
        int[][] matrix2 = {
            {1, 2, 3, 4},
            {5, 6, 7, 8},
            {9, 10, 11, 12}
        };
        output.append("\n// 初始化二维数组\n");
        output.append("int[][] matrix2 = {\n");
        output.append("    {1, 2, 3, 4},\n");
        output.append("    {5, 6, 7, 8},\n");
        output.append("    {9, 10, 11, 12}\n");
        output.append("};\n");
        
        // 2. 不规则数组
        output.append("\n2. 不规则数组（每行长度可不同）：\n");
        int[][] irregular = new int[3][];
        irregular[0] = new int[2];
        irregular[1] = new int[4];
        irregular[2] = new int[3];
        
        output.append("int[][] irregular = new int[3][];\n");
        output.append("irregular[0] = new int[2]; // 第一行2列\n");
        output.append("irregular[1] = new int[4]; // 第二行4列\n");
        output.append("irregular[2] = new int[3]; // 第三行3列\n");
        
        // 3. 多维数组遍历
        output.append("\n3. 多维数组遍历：\n");
        output.append("// 嵌套for循环遍历\n");
        output.append("for (int i = 0; i < matrix2.length; i++) {\n");
        output.append("    for (int j = 0; j < matrix2[i].length; j++) {\n");
        output.append("        int value = matrix2[i][j];\n");
        output.append("    }\n");
        output.append("}\n\n");
        
        output.append("// 嵌套for-each循环遍历\n");
        output.append("for (int[] row : matrix2) {\n");
        output.append("    for (int value : row) {\n");
        output.append("        // 处理每个元素\n");
        output.append("    }\n");
        output.append("}\n");
        
        updateOutput(output.toString());
    }
    
    /**
     * 演示数组的常见错误
     */
    private void demonstrateCommonErrors() {
        StringBuilder output = new StringBuilder();
        output.append("\n=== 数组常见错误 ===\n\n");
        
        // 1. 数组越界
        output.append("1. 数组越界错误：\n");
        output.append("int[] arr = new int[5]; // 索引范围: 0-4\n");
        output.append("arr[5] = 10; // 错误：数组索引越界 (ArrayIndexOutOfBoundsException)\n");
        output.append("arr[-1] = 10; // 错误：数组索引为负数 (ArrayIndexOutOfBoundsException)\n");
        
        // 2. 空指针异常
        output.append("\n2. 空指针异常：\n");
        output.append("int[] arr = null;\n");
        output.append("arr[0] = 10; // 错误：空指针异常 (NullPointerException)\n");
        output.append("int length = arr.length; // 错误：空指针异常 (NullPointerException)\n");
        
        // 3. 错误的数组创建
        output.append("\n3. 错误的数组创建：\n");
        output.append("int[] arr = new int[]; // 错误：必须指定大小\n");
        output.append("int[] arr = [1, 2, 3]; // 错误：应该使用花括号{}\n");
        output.append("int[5] arr; // 错误：声明时不能指定大小\n");
        
        // 4. 类型不匹配
        output.append("\n4. 类型不匹配：\n");
        output.append("int[] intArr = new int[3];\n");
        output.append("String[] strArr = (String[])intArr; // 错误：不能进行这种类型转换\n");
        
        // 5. 循环中的常见错误
        output.append("\n5. 循环中的常见错误：\n");
        output.append("for (int i = 0; i <= arr.length; i++) { // 错误：应该是 < 而不是 <=\n");
        output.append("    // 最后一次循环会导致数组越界\n");
        output.append("}\n\n");
        
        output.append("// 未检查边界的危险操作\n");
        output.append("for (int i = 0; i < arr.length; i++) {\n");
        output.append("    int prev = arr[i-1]; // 危险：当i=0时，会访问arr[-1]导致越界异常\n");
        output.append("}\n");
        
        updateOutput(output.toString());
    }
    
    /**
     * 演示面试中的常见问题
     */
    private void demonstrateInterviewQuestions() {
        StringBuilder output = new StringBuilder();
        output.append("\n=== 面试常见问题 ===\n\n");
        
        // 1. 如何判断两个数组是否相等
        output.append("1. 如何判断两个数组是否相等：\n");
        output.append("// 使用Arrays.equals方法\n");
        output.append("int[] arr1 = {1, 2, 3};\n");
        output.append("int[] arr2 = {1, 2, 3};\n");
        output.append("boolean isEqual = Arrays.equals(arr1, arr2); // true\n\n");
        
        output.append("// 对于多维数组，使用Arrays.deepEquals\n");
        output.append("int[][] matrix1 = {{1, 2}, {3, 4}};\n");
        output.append("int[][] matrix2 = {{1, 2}, {3, 4}};\n");
        output.append("boolean isDeepEqual = Arrays.deepEquals(matrix1, matrix2); // true\n");
        
        // 2. 数组与ArrayList的区别
        output.append("\n2. 数组与ArrayList的区别：\n");
        output.append("- 数组长度固定，ArrayList可动态调整大小\n");
        output.append("- 数组可以存储基本类型，ArrayList只能存储对象\n");
        output.append("- 数组没有内置方法，ArrayList有丰富的API\n");
        output.append("- 数组性能较好，ArrayList有一定开销\n");
        
        // 3. 快速排序、归并排序的时间复杂度
        output.append("\n3. 排序算法时间复杂度：\n");
        output.append("- Arrays.sort() 对基本类型使用双轴快速排序 (Dual-Pivot Quicksort)\n");
        output.append("- 平均时间复杂度：O(n log n)\n");
        output.append("- 最坏时间复杂度：O(n²) [标准快排] 或 O(n log n) [归并排序]\n");
        
        // 4. 浅拷贝与深拷贝
        output.append("\n4. 浅拷贝与深拷贝：\n");
        output.append("- 浅拷贝：复制数组引用，两个变量指向同一数组\n");
        output.append("  int[] original = {1, 2, 3};\n");
        output.append("  int[] shallowCopy = original; // 浅拷贝\n\n");
        
        output.append("- 深拷贝：复制数组内容，创建新的独立数组\n");
        output.append("  int[] deepCopy = new int[original.length];\n");
        output.append("  System.arraycopy(original, 0, deepCopy, 0, original.length);\n");
        output.append("  或者：int[] deepCopy = Arrays.copyOf(original, original.length);\n");
        
        // 5. 为什么数组索引从0开始
        output.append("\n5. 为什么数组索引从0开始：\n");
        output.append("- 历史原因：C语言的设计决定\n");
        output.append("- 性能原因：计算内存地址时offset = base + index * size 更高效\n");
        output.append("- 数学原因：区间[0,n)表示n个元素，逻辑更清晰\n");
        
        updateOutput(output.toString());
    }
    
    /**
     * 更新输出文本
     */
    private void updateOutput(String text) {
        tvOutput.append(text);
    }
} 